<?php

namespace App\Console\Scripts\Counter;

use App\Consts\GlobalConst;
use App\Consts\GlobalCounterConst;
use App\Consts\GlobalNoteConst;
use App\Consts\GlobalRelationshipConst;
use App\Models\Cache\CacheKey;
use App\Models\SysDynamic;
use App\Models\SysNote;
use App\Models\User;
use App\Models\UserCollect;
use App\Models\UserCollectPackage;
use App\Models\UserFollowingRelationship;
use Illuminate\Database\Query\Builder;

/**
 * 用户计数统计脚本
 * Class ArticleCounterCommand
 * @package App\Console\Scripts\Counter
 */
class UserCounterCommand extends BaseCounterCommand
{

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'counter:user {action} {--ids=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'counter for user';

    /**
     * 用户收藏夹统计
     * @return int
     */
    public function package()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->user_id;
                $total = UserCollectPackage::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('user_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['user_id' => $id],
                    CacheKey::COUNTER_USER,
                    [GlobalCounterConst::COUNT_COLLECT_PACKAGE => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_COLLECT_PACKAGE." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'user_id');
        return 1;
    }

    /**
     * 用户公开笔记统计
     * @return int
     */
    public function notePublic()
    {
        return $this->_setNoteCount(GlobalNoteConst::IS_PUBLIC, GlobalCounterConst::COUNT_PUBLIC_NOTE);
    }

    /**
     * 用户私有笔记统计
     * @return int
     */
    public function noteSelf()
    {
       return $this->_setNoteCount(GlobalNoteConst::IS_NOT_PUBLIC, GlobalCounterConst::COUNT_SELF_NOTE);
    }

    /**
     * 用户收藏内容统计
     * @return int
     */
    public function collect()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->user_id;
                $total = UserCollect::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('user_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['user_id' => $id],
                    CacheKey::COUNTER_USER,
                    [GlobalCounterConst::COUNT_COLLECT => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_COLLECT." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'user_id');
        return 1;
    }

    /**
     * 用户关注统计
     * @return int
     */
    public function attention()
    {
        return $this->_setRelationCount(
            [GlobalRelationshipConst::ATTENTION_STATUS_ATTENTION, GlobalRelationshipConst::ATTENTION_STATUS_EACH],
            GlobalCounterConst::COUNT_ATTENTION
        );
    }

    /**
     * 用户粉丝统计
     * @return int
     */
    public function fans()
    {
        return $this->_setRelationCount(
            [GlobalRelationshipConst::ATTENTION_STATUS_FANS, GlobalRelationshipConst::ATTENTION_STATUS_EACH],
            GlobalCounterConst::COUNT_FANS
        );
    }

    /**
     * 用户动态统计
     * @return int
     */
    public function dynamic()
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->user_id;
                $total = SysDynamic::getSubModel(function (Builder $query) use ($id) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('user_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['user_id' => $id],
                    CacheKey::COUNTER_USER,
                    [GlobalCounterConst::COUNT_DYNAMIC => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".GlobalCounterConst::COUNT_DYNAMIC." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'user_id');
        return 1;
    }

    /**
     * set note count
     * @param $type
     * @param $key
     * @return int
     */
    private function _setNoteCount($type, $key)
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish, $type, $key) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->user_id;
                $total = SysNote::getSubModel(function (Builder $query) use ($id, $type) {
                    $query->where('is_deleted', GlobalConst::IS_NOT_DELETE);
                    $query->where('is_shield', GlobalNoteConst::IS_NOT_SHIELD);
                    $query->where('is_public', $type);
                    $query->where('user_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['user_id' => $id],
                    CacheKey::COUNTER_USER,
                    [$key => $total]
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".$key." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'user_id');
        return 1;
    }

    /**
     * set relation count
     * @param $type
     * @param $key
     * @return int
     */
    private function _setRelationCount($type, $key)
    {
        $subMode = $this->_getSubModel();
        $finish = $subMode->count();
        // 每 100 单位合并处理一次
        $subMode->chunkById(100, function ($list) use ($finish, $type, $key) {
            foreach ($list as $item) {
                static $index = 1;
                $id = $item->user_id;
                $total = UserFollowingRelationship::getSubModel(function (Builder $query) use ($id, $type) {
                    $query->whereIn('attention_status', $type);
                    $query->where('user_id', $id);
                }, ['id'])->count();
                // set cache
                $cacheKey = $this->setHashCache(
                    ['user_id' => $id],
                    CacheKey::COUNTER_USER,
                    [$key => $total],
                    true
                );
                // log info
                $info = "[$index/$finish] set cache key `$cacheKey` - ".$key." {$this->sort} to (int) $total";
                $this->info($info);
                if ($total) $this->logger($info, false, 'script');
                $index++;
            }
        }, 'user_id');
        return 1;
    }

    /**
     * get sub user
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|mixed
     */
    private function _getSubModel()
    {
        $ids = $this->option('ids');
        $idAry = $ids ? explode(',', $ids) : [];
        $subMode = User::getModel()
            ->select(['id', 'user_id'])
            ->when($idAry, function ($query) use ($idAry) {$query->whereIn('user_id', $idAry);})
            ->where('is_deleted', GlobalConst::IS_NOT_DELETE);
        return $subMode;
    }

}
